﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using RacePlatformer.Object;
using FarseerPhysics.Dynamics;
using System.Xml;
using Dwarfs.Object;
using Dwarfs.Object.Boss;

namespace RacePlatformer.Manager
{
    public class GameObjectManager
    {
        private const float MAP_WIDTH = 4096;
        private const float MAP_HEIGHT = 2000;
        private System.Xml.XmlTextReader xmlReader;
        public List<GameObject> gameObjects;
        private World world;
        private MainGame maingame;
        public int amountofPlayersSpawning = 0;
        //for reading from the xml file.
        String property = "";
        String objectname = "";
        /// <summary>
        /// The class that reads allt he objects from the xml file and then places them accordingly.
        /// </summary>
        /// <param name="maingame">The 'MainGame.cs' class</param>
        /// <param name="world">The 'world' class</param>
        public GameObjectManager(MainGame maingame, World world, int levelID)
        {
            this.maingame = maingame;
            this.world = world;
            gameObjects = new List<GameObject>();
            loadObjects(levelID);
        }
        public void destoryAllObjects(int levelID)
        {
            for (int i = 0; i < gameObjects.Count; i++)
            {
                gameObjects[i].body.Dispose();
                gameObjects[i] = null;
            }
            gameObjects = new List<GameObject>();
        }
        public void Update(GameTime gametime)
        {
            for (int i = 0; i < gameObjects.Count; i++) gameObjects.ElementAt(i).Update(gametime);
        }
        public void Draw(GameTime gametime, SpriteBatch batch)
        {
            for (int i = 0; i < gameObjects.Count; i++) gameObjects.ElementAt(i).Draw(gametime, batch);
        }
        /// <summary>
        /// Adds an object to the game.
        /// </summary>
        /// <param name="gameObject"></param>
        public void addObject(GameObject gameObject)
        {
            gameObjects.Add(gameObject);
        }
        private void loadObjects(int levelID)
        {
            xmlReader = new System.Xml.XmlTextReader("ObjectList/level" + levelID + ".xml");
            loopThroughObjects();
        }
        /// <summary>
        /// Function to loop through the xml file and read the objects from it.
        /// How it works : Firstly you create local variables with the values that will be filled.
        /// After that you check what kind of node it is, is its a name node, the name will be
        /// filled in as property, after if it finds a 'text' node, it
        /// checks the property node and fills in the proper property.
        /// if its finds an end node it checks the objectname(which is filled in last)
        /// and then it adds the object to the manager.
        /// </summary>
        private void loopThroughObjects()
        {
            //temp
            GameObject gameObject = null;
            String[] size = new String[2], position = new String[2];
            BodyType bodytype = BodyType.Dynamic;
            float mass = 1f, width = 1, height = 1, x = 1, y = 1;
            int levelID = 0;
            while (xmlReader.Read())
            {
                switch (xmlReader.NodeType)
                {
                    case XmlNodeType.Element: //Display element
                        property = xmlReader.Name;
                        break;
                    case XmlNodeType.Text: //Display the text in each element.
                        switch (property)
                        {
                            case "amountPlayers": amountofPlayersSpawning = (int)Convert.ToDouble(xmlReader.Value); break;
                            case "id": levelID = (int)Convert.ToDouble(xmlReader.Value); break;
                            case "name": objectname = xmlReader.Value; break;
                            case "mass": mass = (float)Convert.ToDouble(xmlReader.Value); break;
                            case "size":
                                size = xmlReader.Value.ToString().Split(':');
                                width = (float)Convert.ToDouble(size[0]);
                                height = (float)Convert.ToDouble(size[1]);
                                break;
                            case "position":
                                position = xmlReader.Value.ToString().Split(':');
                                x = (float)Convert.ToDouble(position[0]);
                                y = (float)Convert.ToDouble(position[1]);
                                break;
                            case "bodytype":
                                switch (xmlReader.Value)
                                {
                                    case "Kinematic": bodytype = BodyType.Kinematic; break;
                                    case "Static": bodytype = BodyType.Static; break;
                                    case "Dynamic": bodytype = BodyType.Dynamic; break;
                                }
                                break;
                        }
                        break;
                    case XmlNodeType.EndElement: //Display the end of the element.
                        switch (objectname)
                        {
                            case "Ground_base":
                                gameObject = new GroundObject(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "Box":
                                gameObject = new BoxObject(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "Wall":
                                gameObject = new WallObject(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "SavePoint":
                                gameObject = new SaveState(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "Candy":
                                gameObject = new Candy(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "CircleSaw":
                                gameObject = new CircleSaw(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "Boss":
                                gameObject = new Boss(maingame, world, new Vector2(width, height), new Vector2(x, y), bodytype, mass, levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                            case "Monster":
                                gameObject = new Monster(maingame, world, new Vector2(x, y), levelID);
                                addObject(gameObject);
                                resetValues();
                                break;
                        }

                        break;
                }
            }
        }
        private void resetValues()
        {
            property = ""; objectname = "";
        }
    }
}
